package com.artup.service.impl;

import java.sql.SQLException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.AlipayTradeAppPayModel;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.AlipayTradeAppPayRequest;
import com.alipay.api.request.AlipayTradeQueryRequest;
import com.alipay.api.response.AlipayTradeAppPayResponse;
import com.alipay.api.response.AlipayTradeQueryResponse;
import com.artup.common.Constants;
import com.artup.common.OrderStatus;
import com.artup.common.PaymentStatus;
import com.artup.common.ResponseResult;
import com.artup.dao.OrderDao;
import com.artup.dao.PaymentDao;
import com.artup.pojo.AliPayResult;
import com.artup.pojo.Order;
import com.artup.pojo.Payment;
import com.artup.service.AlipayService;
import com.artup.service.MesService;
import com.artup.util.file.PropertiesUtils;

/**
 * 支付宝
 * @author hapday
 * @date 2017年7月24日 @Time 下午7:03:05
 */
@Service( value = "alipayService" )
public class AlipayServiceImpl implements AlipayService {
	private static final Logger LOGGER = LoggerFactory.getLogger(AlipayServiceImpl.class);
	
	@Autowired
	private OrderDao orderDao;
	
	@Autowired
	private PaymentDao paymentDao;
	
	@Autowired
	private PdfServiceImpl pdfService;
	
	@Autowired
	private MesService mesService;
	
	private final String CHARSET = "UTF-8";		// 字符编码
	private final String APP_ID = PropertiesUtils.getValue("alipay.pay.appId");		// APP_ID
	private final String APP_PRIVATE_KEY = PropertiesUtils.getValue("alipay.pay.appPrivateKey");		// APP_ID
	private final String ALIPAY_PUBLIC_KEY = PropertiesUtils.getValue("alipay.pay.alipayPublicKey");	// 公钥
	private final String ALIPAY_GATEWAY_API = PropertiesUtils.getValue("alipay.pay.api.gateway");	// 接口网关
	private final String ALIPAY_CALLBACK_API = PropertiesUtils.getValue("alipay.pay.api.callback");	// 支付回调接口

	@Override
	public ResponseResult createAlipayOrder(String orderCode, float totalFee, String worksName) {
		LOGGER.info("orderCode = {}, totalFee = {}, worksName = {}", orderCode, totalFee, worksName);
		
		ResponseResult responseResult = new ResponseResult();
		
		if(StringUtils.isBlank(orderCode)){
			responseResult.setStatus(Constants.ACTION_STATUS_PARAMETER_EMPTY);
			responseResult.setMessage("无【订单号】！");
			
			return responseResult;
		}
		
		Order order = null;
		try {
			order = this.orderDao.selectOrderByCode(orderCode);
		} catch (SQLException e) {
			LOGGER.error("根据【编号】查询【订单详情】- 失败！", e);
			
			responseResult.setStatus(Constants.ACTION_STATUS_FAILURE);
			responseResult.setMessage("根据【编号】查询【订单详情】- 失败！");
			
			return responseResult;
		}
		
		if(null == order) {
			responseResult.setStatus(Constants.ACTION_STATUS_RESULT_EMPTY);
			responseResult.setMessage("无此订单！");
			
			return responseResult;
		}
		
		order.setTotalPrice(0.01F);		// test
		
		//实例化客户端
		AlipayClient alipayClient = new DefaultAlipayClient(ALIPAY_GATEWAY_API, APP_ID, APP_PRIVATE_KEY, "json", CHARSET, ALIPAY_PUBLIC_KEY, "RSA2");
		//SDK已经封装掉了公共参数，这里只需要传入业务参数。以下方法为sdk的model入参方式(model和biz_content同时存在的情况下取biz_content)。
		AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();
		model.setBody("This is alipay order.");
		model.setSubject(worksName);
		model.setOutTradeNo(orderCode);
		model.setTimeoutExpress("30m");
//		model.setTotalAmount(String.valueOf(totalFee));
		model.setTotalAmount(String.valueOf(order.getTotalPrice()));
		model.setProductCode("QUICK_MSECURITY_PAY");
		
		//实例化具体API对应的request类,类名称和接口名称对应,当前调用接口名称：alipay.trade.app.pay
		AlipayTradeAppPayRequest request = new AlipayTradeAppPayRequest();
		request.setBizModel(model);
		request.setNotifyUrl(ALIPAY_CALLBACK_API);
		
		AlipayTradeAppPayResponse alipayTradeAppPayResponse = null;
		try {
			// 这里和普通的接口调用不同，使用的是sdkExecute
			alipayTradeAppPayResponse = alipayClient.sdkExecute(request);
		} catch (AlipayApiException e) {
			LOGGER.error("创建支付宝预支付信息 - 失败！");

			responseResult.setStatus(Constants.ACTION_STATUS_FAILURE);
			responseResult.setMessage("创建支付宝预支付信息 - 失败！");
		}

		if(null != alipayTradeAppPayResponse) {
			// 就是orderString	// 可以直接给客户端请求，无需再做处理。
			LOGGER.info("alipayTradeAppPayResponse = {}", alipayTradeAppPayResponse.getBody());
		}
		
		responseResult.setStatus(Constants.ACTION_STATUS_SUCCESS);
		responseResult.setMessage("创建支付宝预支付信息 - 成功。");
		responseResult.setData(alipayTradeAppPayResponse.getBody());
		
		return responseResult;
	}
	
	@Override
	public ResponseResult queryAlipayOrder(String orderCode, String alipayOrderCode) {
		LOGGER.info("orderCode = {}, alipayOrderCode = {}", orderCode, alipayOrderCode);
		
		ResponseResult responseResult = new ResponseResult();
		
		if(StringUtils.isBlank(orderCode) && StringUtils.isBlank(alipayOrderCode)){
			responseResult.setStatus(Constants.ACTION_STATUS_PARAMETER_EMPTY);
			responseResult.setMessage("【订单号】和【支付宝订单号】不可同时为空！");
			
			return responseResult;
		}
		
//		https://docs.open.alipay.com/api_1/alipay.trade.query
		
		// 实例化客户端
		AlipayClient alipayClient = new DefaultAlipayClient(ALIPAY_GATEWAY_API, APP_ID, APP_PRIVATE_KEY, "json", CHARSET, ALIPAY_PUBLIC_KEY, "RSA2");
		AlipayTradeQueryRequest alipayTradeQueryRequest = new AlipayTradeQueryRequest();
		alipayTradeQueryRequest.setBizContent("{" + "\"out_trade_no\":\"" + orderCode + "\"," + "\"trade_no\":\"" + alipayOrderCode + "\"" + "  }");
		AlipayTradeQueryResponse alipayTradeQueryResponse = null;
		try {
			alipayTradeQueryResponse = alipayClient.execute(alipayTradeQueryRequest);
		} catch (AlipayApiException e) {
			LOGGER.error("查询【支付宝支付订单】 - 失败！", e);
			
			responseResult.setStatus(Constants.ACTION_STATUS_FAILURE);
			responseResult.setMessage("查询【支付宝支付订单】 - 失败！");
			
			return responseResult;
		}
		
		if(null == alipayTradeQueryResponse) {
			LOGGER.error("【支付宝支付订单】结果为空！");
			
			responseResult.setStatus(Constants.ACTION_STATUS_RESULT_EMPTY);
			responseResult.setMessage("【支付宝支付订单】结果为空！！");
			
			return responseResult;
		}
		
		LOGGER.info("alipayTradeQueryResponse = {}", alipayTradeQueryResponse.getBody());
		
		if (alipayTradeQueryResponse.isSuccess()) {
			System.out.println("调用成功");
		} else {
			System.out.println("调用失败");
		}
		
		byte orderStatus = 0;
		try {
			orderStatus = this.orderDao.selectOrderStatusByCode(orderCode);
		} catch (SQLException e) {
			responseResult.setStatus(Constants.ACTION_STATUS_FAILURE);
			responseResult.setMessage("根据【订单号】查询【订单状态】 - 失败！");
			
			return responseResult;
		}
		
		if(!(OrderStatus.getValue(OrderStatus.PAID) == orderStatus)) {
			responseResult.setStatus(Constants.ACTION_STATUS_FAILURE);
			responseResult.setMessage("未支付成功！");
			
			return responseResult;
		}
		
		responseResult.setStatus(Constants.ACTION_STATUS_SUCCESS);
		responseResult.setMessage("查询【支付宝支付订单】 - 成功。");
		responseResult.setData(alipayTradeQueryResponse.getBody());
		
		return responseResult;
	}
	
	@Override
	public ResponseResult aliPayCallback(HttpServletRequest request) {
		LOGGER.info("---------------------- 支付宝回调 - begin ----------------------");
		
		ResponseResult responseResult = new ResponseResult();
		
		// 获取支付宝POST过来反馈信息
		Map<String, String> payResultMap = new HashMap<String, String>();
		
		Map<String, String[]> requestParams = request.getParameterMap();
		
		for (Iterator<String> iter = requestParams.keySet().iterator(); iter.hasNext();) {
		    String name = (String) iter.next();
		    LOGGER.info("name = {}", name);
		    
		    String[] values = (String[]) requestParams.get(name);
		    
		    String valueStr = "";
		    for (int i = 0; i < values.length; i++) {
		    	valueStr = (i == values.length - 1) ? valueStr + values[i]
		                : valueStr + values[i] + ",";
		    	LOGGER.info("valueStr = {}", valueStr);
		    }
			//乱码解决，这段代码在出现乱码时使用。
		  	//valueStr = new String(valueStr.getBytes("ISO-8859-1"), "utf-8");
			payResultMap.put(name, valueStr);
		}
		
		LOGGER.info("payResultMap = {}", payResultMap);
		//切记alipaypublickey是支付宝的公钥，请去open.alipay.com对应应用下查看。
		//boolean AlipaySignature.rsaCheckV1(Map<String, String> params, String publicKey, String charset, String sign_type)
		try {
			boolean flag = AlipaySignature.rsaCheckV1(payResultMap, ALIPAY_PUBLIC_KEY, CHARSET, "RSA2");
			LOGGER.info("flag = {}", flag);
		} catch (AlipayApiException e) {
			LOGGER.error("支付宝 RSA 验签失败！", e);
			
			responseResult.setStatus(Constants.ACTION_STATUS_FAILURE);
			responseResult.setMessage("支付宝 RSA 验签失败！");
			
			return responseResult;
		}
		
		if(!"TRADE_SUCCESS".equals(payResultMap.get("trade_status"))) {
			responseResult.setStatus(Constants.ACTION_STATUS_FAILURE);
			
			if("TRADE_CLOSED".equals(payResultMap.get("trade_status"))) {
				responseResult.setMessage("交易已关闭！");
			} else if("TRADE_FINISHED".equals(payResultMap.get("trade_status"))) {
				responseResult.setMessage("交易已结束！");
			}
			
			return responseResult;
		}
		
		AliPayResult aliPayResult = JSONObject.parseObject(JSONObject.toJSONString(payResultMap), AliPayResult.class);
		
		String orderCode = aliPayResult.getOut_trade_no();
		String trade_no = aliPayResult.getTrade_no();
		String total_amount = aliPayResult.getTotal_amount();
		
		Order order = new Order();
		order.setCode(orderCode);
		order.setStatus(OrderStatus.getValue(OrderStatus.PAID));
		order.setTransactionCode(trade_no);
		order.setModifierId(0L);
		
		try {
			this.orderDao.updateOrderByCode(order);
		} catch (SQLException e) {
			LOGGER.error("根据【订单号】更新【订单状态】 - 失败！");
			
			responseResult.setStatus(Constants.ACTION_STATUS_FAILURE);
			responseResult.setMessage("根据【订单号】更新【订单状态】 - 失败！");
			
			return responseResult;
		}
		
		Payment payment = new Payment();
		payment.setOrderCode(orderCode);
		payment.setType("alipay");
		payment.setStatus(PaymentStatus.getValue(PaymentStatus.PAID));
		if(StringUtils.isBlank(total_amount)) {
			payment.setTotalPrice(0F);
		} else {
			payment.setTotalPrice(Float.parseFloat(total_amount));
		}
		
		try {
			this.paymentDao.updatePaymentByOrderCode(payment);
		} catch (SQLException e) {
			LOGGER.error("根据【订单编号】更新【支付流水】 - 失败！", e);
			
			responseResult.setStatus(Constants.ACTION_STATUS_FAILURE);
			responseResult.setMessage("根据【订单编号】更新【支付流水】 - 失败！");
			
			return responseResult;
		}
		
		this.pdfService.createPdf(orderCode);
		
		this.mesService.noticeMesOrder(orderCode);

		LOGGER.info("---------------------- 支付宝回调 - end ----------------------");
		
		responseResult.setStatus(Constants.ACTION_STATUS_SUCCESS);
		responseResult.setMessage("【支付宝】支付成功 - 成功。");
		
		return responseResult;
	}
}
